﻿using System;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Net;

namespace IveelySE.Dream.Common.Transmission
{
    internal class ClientHelper
    {
        /// <summary>
        /// 客户端数据接收
        /// </summary>
        /// <param name="client"></param>
        /// <param name="data"></param>
        public delegate void ReceiveData(TcpClient client, string data);

        public static ReceiveData delReceiveData = null;

        /// <summary>
        /// 数据接收大小
        /// </summary>
        private const int READ_BUFFER_SIZE = 5120;

        /// <summary>
        /// 接收的字节内容
        /// </summary>
        private static byte[] readBuffer = new byte[READ_BUFFER_SIZE];

        /// <summary>
        /// 连接主机
        /// </summary>
        /// <param name="client">连接的客户端</param>
        /// <param name="remoteHost">远程主机地址</param>
        /// <param name="remotePort">远程主机端口</param>
        /// <param name="asyncCallback">异步回调用</param>
        /// <returns>返回是否连接成功</returns>
        public static bool ConnectSocket(ref TcpClient client, string remoteHost, int remotePort, AsyncCallback asyncCallback)
        {
            try
            {
                if (client == null || client.Client == null)
                {
                    client = new TcpClient();
                }

                if (client.Connected)
                {
                    Console.WriteLine("Re-Connect\t" + DateTime.Now.ToString() + "\t" +
                        "close current connect\t" + client.GetHashCode().ToString());

                    if (client.GetStream() != null)
                    {
                        client.GetStream().Close();
                    }

                    client.Close();
                    client = new TcpClient();

                    Console.WriteLine("Create Client\t" + DateTime.Now.ToString() + "\t" +
                        client.GetHashCode().ToString());
                }

                try
                {
                    client.Connect(remoteHost, remotePort);
                }
                catch (ObjectDisposedException)
                {
                    client = new TcpClient();
                    client.Connect(remoteHost, remotePort);

                    Console.WriteLine("Create Client\t" + DateTime.Now.ToString() + "\t" +
                        client.GetHashCode().ToString());
                }

                client.GetStream().BeginRead(readBuffer, 0,
                    READ_BUFFER_SIZE, asyncCallback, client);
                return true;
            }
            catch
            {
                if (client != null)
                {
                    client.Close();
                }
            }

            return false;
        }


        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <param name="client">连接客户端</param>
        public static void Close(TcpClient client)
        {
            if (client == null)
            {
                return;
            }

            if (client.GetStream() != null)
            {
                client.GetStream().Close();
            }
            client.Close();
            System.Threading.Thread.Sleep(100);
        }

        public void DoReading(IAsyncResult asyncResult)
        {
            int bytesRead = 0;
            string receivedData = string.Empty;
            TcpClient client = null;
            try
            {
                client = (TcpClient)asyncResult.AsyncState;

                if (client.Connected)
                {
                    lock (client.GetStream())
                    {
                        bytesRead = client.GetStream().EndRead(asyncResult);
                    }
                }

                if (bytesRead > 0)
                {
                    receivedData = Encoding.UTF8.GetString(readBuffer, 0, bytesRead);

                    (new ReceiveData(HandleReceive)).BeginInvoke(client, receivedData,
                        new AsyncCallback(ReceiveCallback), client);
                }
                else
                {
                    client.Close();

                    Console.WriteLine("Connect Closed\t" + DateTime.Now.ToString() + "\t" +
                        client.GetHashCode().ToString());

                    return;
                }
            }
            catch
            {

            }
          
        }

        /// <summary>
        /// 客户端接收到服务端信息处理
        /// </summary>
        /// <param name="client"></param>
        /// <param name="data"></param>
        public static void HandleReceive(TcpClient client, string data)
        {
            Console.WriteLine("Receive\t\t" + DateTime.Now.ToString() + "\t" +
                client.GetHashCode().ToString() + "\t" + data);
        }

        /// <summary>
        /// 接收回掉
        /// </summary>
        /// <param name="asyncResult"></param>
        private void ReceiveCallback(IAsyncResult asyncResult)
        {
            TcpClient client = null;
            try
            {
                client = (TcpClient)asyncResult.AsyncState;

                lock (client.GetStream())
                {
                    client.GetStream().BeginRead(readBuffer, 0,
                        READ_BUFFER_SIZE, new AsyncCallback(DoReading), client);
                }
            }
            catch
            { }

            //finally
            //{
            //    if (client != null)
            //    {
            //        client.Close();
            //    }
            //}
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="client">连接客户端</param>
        /// <param name="sendMessage">发送的信息</param>
        /// <returns>返回是否发送成功</returns>
        public static bool SendObjectMessage(TcpClient client, string sendMessage)
        {
            Byte[] data = null;
            NetworkStream networkStream = null;
            try
            {
                ClientInfo info = new ClientInfo();
                info.IP = GetIP();
                info.Information = sendMessage;
                data = Serializer.Serialize(info);
                lock (client.GetStream())
                {
                    networkStream = client.GetStream();
                    networkStream.Write(data, 0, data.Length);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="client">连接客户端</param>
        /// <param name="sendMessage">发送的信息</param>
        /// <returns>返回是否发送成功</returns>
        public static bool SendMessage(TcpClient client, string message)
        {
            byte[] data = null;
            NetworkStream networkStream = null;
            try
            {
                data = Encoding.UTF8.GetBytes(message);
                lock (client.GetStream())
                {
                    networkStream = client.GetStream();
                    networkStream.Write(data, 0, data.Length);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 获取本机IP
        /// </summary>
        /// <returns>返回IP字符串</returns>
        private static string GetIP()
        {
            IPHostEntry ipHost = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddr = ipHost.AddressList[0];
            return ipAddr.ToString();
        }
    }
}
